#include "cJSON.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include <errno.h>
#include <stdarg.h>
#include <time.h>
#include <sys/types.h>
#include "comm.h"

#define		CONF_FILE	"/usr/local/s2n.conf"


#define     CHECK(s)    do{\
                        if(!(s))\
                            goto end;\
                        }while(0)


#define   ERROR_OK 	0
#define   ERROR_FAIL	-1
#define   ERROR_PARAM	-2


#define	 VALUED_OK		1
#define	 VALUED_ERR		0



int zc_profile_inner(const char *file, const long line, const char *fmt, ...)
{
	va_list args;
	
	if(NULL == file){
		return ERROR_FAIL;
	}
	
	printf("DEBUG (%s:%ld): ", file, line);
	va_start(args, fmt);
	vprintf(fmt, args);
	va_end(args);
	printf("\n");

	return ERROR_OK;
}



//从文件中读取json数据
static cJSON * JsonFromFile(const char *filename)
{
	if(NULL == filename){
		return NULL;
	}
	
	FILE *f = NULL;
	long len;
	char *data;
	cJSON *root = NULL;
	
	f=fopen(filename,"rb");
	if(NULL == f){
		printf("open %s failed \n", filename);
		return NULL;
	}
	fseek(f,0,SEEK_END);
	len=ftell(f);
	fseek(f,0,SEEK_SET);
	
	//读取文件数据
	data=(char*)malloc(len+1);
	if(NULL == data){
		printf("malloc failed \n");
		fclose(f);
		return NULL;
	}
	fread(data,1,len,f);
	fclose(f);
	root = cJSON_Parse(data);
	free(data);
	
	return root;
}



//保存json格式数据到文件中
static int SaveJsonToFile(const char *filename, cJSON *root)
{
	if(NULL == filename || NULL == root){
		return -1;
	}

	FILE *f = fopen(filename, "w+");
	if(NULL == f){
		return -1;
	}
	char *s = cJSON_Print(root);
	fwrite(s, 1, strlen(s), f);
	free(s);
	fclose(f);
	return 0;
}



//判断IP地址是否合法，合法返回1，不合法返回0
static int isVaildIp(const char *ip)
{
    int dots = 0; /*字符.的个数*/
    int setions = 0; /*ip每一部分总和（0-255）*/ 

    if (NULL == ip || *ip == '.') { /*排除输入参数为NULL, 或者一个字符为'.'的字符串*/ 
        return 0;
    }   

    while (*ip) {

        if (*ip == '.') {
            dots ++; 
            if (setions >= 0 && setions <= 255) { /*检查ip是否合法*/
                setions = 0;
                ip++;
                continue;
            }   
            return 0;
        }   
        else if (*ip >= '0' && *ip <= '9') { /*判断是不是数字*/
            setions = setions * 10 + (*ip - '0'); /*求每一段总和*/
        } else 
            return 0;
        ip++;   
    }
	//判断最后一个数字的合法性
	if ((setions >= 0) && (setions <= 255)) {
        if (dots == 3) {
            return 1;
        }   
    }   

    return 0;
}


//解析串口配置
static int GetComDev(cJSON * root, comConf *com)
{
	int ret = 0;
	cJSON *item;

	if((NULL == root) || (NULL == com)){
		return ERROR_FAIL;
	}

	item = cJSON_GetObjectItem(root, "status");
	if((NULL == item) || item->valueint == 0){
		return -2;
	}

	item = cJSON_GetObjectItem(root, "baud");
	CHECK(item);
	com->baud = item->valueint;

	item = cJSON_GetObjectItem(root, "parity");
	CHECK(item && item->valuestring);
	com->parity = *(item->valuestring);

	item = cJSON_GetObjectItem(root, "databits");
	CHECK(item);
	com->databits = item->valueint;

	item = cJSON_GetObjectItem(root, "num");
	CHECK(item);
	com->num = item->valueint;

	item = cJSON_GetObjectItem(root, "stop");
	CHECK(item);
	com->stop = item->valueint;

	com->valued = VALUED_OK;

	return ERROR_OK;
end:
	com->valued = VALUED_ERR;
	zc_debug("get com dev failed \n");
	return ERROR_FAIL;
}


//解析服务器配置
static int GetServerInfo(cJSON * root, netInfo *net)
{
	if((NULL == root) || (NULL == net)){
		return ERROR_FAIL;
	}

	cJSON *item;

	item = cJSON_GetObjectItem(root, "ip");
	CHECK(item && item->valuestring);
	strcpy(net->ip, item->valuestring);

	item = cJSON_GetObjectItem(root, "port");
	CHECK(item);
	net->port = item->valueint;
	
	if(net->port > 65535){
		goto end;
	}

	item = cJSON_GetObjectItem(root, "enable");
	if(item){
		net->enable = item->valueint;
	}

	item = cJSON_GetObjectItem(root, "protocal");
	CHECK(item);
	net->protocal = item->valueint;

	CHECK(isVaildIp(net->ip));

	return ERROR_OK;

end:
	return ERROR_FAIL;
}


//解析配置文件
int ParseDevConf(sysConf *sys)
{
	if(!sys){
		return -1;
	}

	cJSON *tree, *root, *item, *arr;
	int size = 0;
	int i = 0;
	int ret;

	tree = JsonFromFile(CONF_FILE);
	if(!tree){
		return ERROR_FAIL;
	}

	arr = cJSON_GetObjectItem(tree, "com");
	CHECK(arr);

	sys->cnt_com = 0;
	size = cJSON_GetArraySize(arr);
	for(i=0; i<size; i++){
		root = cJSON_GetArrayItem(arr, i);
		CHECK(root);
		ret = GetComDev(root, &(sys->com[i]));
		if(-2 == ret){
			continue;
		}
		CHECK(ERROR_OK == ret);
		sys->cnt_com++;
	}

	arr = cJSON_GetObjectItem(tree, "net");
	CHECK(arr);

	sys->cnt_net = 0;
	size = cJSON_GetArraySize(arr);
	for(i=0; i<size; i++){
		root = cJSON_GetArrayItem(arr, i);
		CHECK(root);
		ret = GetServerInfo(root, &(sys->net[i]));
		CHECK(ERROR_OK == ret);
		sys->cnt_net++;
	}

	item = cJSON_GetObjectItem(tree, "crash_size");
	if(item){
		sys->crash_size = item->valueint;
	}else{
		sys->crash_size = 200;
	}

	cJSON_Delete(tree);
	return ERROR_OK;

end:
	cJSON_Delete(tree);
	return ERROR_FAIL;
}


